#[cfg(test)]
mod tests {
    use super::*;
    use crate::router::{Router, Route};
    use crate::filter::{FilterChain, AuthFilter, RateLimitFilter, LoggingFilter, FilterResult, RequestFilter};
    use crate::gateway::{GatewayConfig, GatewayState, SimpleGateway};
    use async_trait::async_trait;
    use axum::http::{HeaderMap, StatusCode, HeaderName, HeaderValue};
    use rustcloud_core::{
        ServiceRegistry, LoadBalancer, Transport, CircuitBreaker, ServiceInstance, 
        Request, Response, ServiceResult, ServiceError, RegistryConfig, RegistryType,
        LoadBalancerStrategy, CircuitBreakerConfig, CircuitBreakerState, ServiceWatcher,
        CircuitBreakerMetrics, StrategyInfo
    };
    use std::collections::HashMap;
    use std::sync::Arc;
    use std::time::{Duration, Instant};
    use tokio::sync::RwLock;

    // Mock implementations for testing

    struct MockRegistry {
        instances: Arc<RwLock<HashMap<String, Vec<ServiceInstance>>>>,
    }

    impl MockRegistry {
        fn new() -> Self {
            Self {
                instances: Arc::new(RwLock::new(HashMap::new())),
            }
        }

        async fn add_instance(&self, service_name: &str, instance: ServiceInstance) {
            let mut instances = self.instances.write().await;
            instances.entry(service_name.to_string()).or_insert_with(Vec::new).push(instance);
        }
    }

    #[async_trait]
    impl ServiceRegistry for MockRegistry {
        async fn register(&self, _instance: ServiceInstance) -> ServiceResult<()> { Ok(()) }
        async fn deregister(&self, _instance: ServiceInstance) -> ServiceResult<()> { Ok(()) }
        async fn discover(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
            let instances = self.instances.read().await;
            Ok(instances.get(service_name).cloned().unwrap_or_default())
        }
        async fn health_check(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
            let instances = self.discover(service_name).await?;
            Ok(instances.into_iter().filter(|i| i.healthy).collect())
        }
        async fn watch(&self, _service_name: &str) -> ServiceResult<Box<dyn ServiceWatcher + Send>> {
            unimplemented!("Mock registry doesn't support watching")
        }
    }

    struct MockLoadBalancer;

    #[async_trait]
    impl LoadBalancer for MockLoadBalancer {
        async fn select(&self, _service_name: &str, instances: &[ServiceInstance]) -> ServiceResult<Option<ServiceInstance>> {
            Ok(instances.first().cloned())
        }
        
        fn name(&self) -> &str { "mock" }
        
        fn get_strategy_info(&self) -> StrategyInfo {
            StrategyInfo {
                name: "mock".to_string(),
                description: "Mock load balancer for testing".to_string(),
                requires_session_affinity: false,
                supports_weighted_routing: false,
            }
        }
    }

    struct MockTransport {
        response: Response,
    }

    impl MockTransport {
        fn new(status: u16) -> Self {
            Self {
                response: Response::new(status),
            }
        }

        fn with_body(mut self, body: Vec<u8>) -> Self {
            self.response.body = Some(body);
            self
        }
    }

    #[async_trait]
    impl Transport for MockTransport {
        async fn send(&self, _request: Request, _instance: &ServiceInstance) -> ServiceResult<Response> {
            Ok(self.response.clone())
        }
        
        async fn send_batch(
            &self,
            requests: Vec<(Request, &ServiceInstance)>,
        ) -> Vec<ServiceResult<Response>> {
            requests.into_iter().map(|_| Ok(self.response.clone())).collect()
        }
        
        fn name(&self) -> &str { "mock" }
    }

    struct MockCircuitBreaker {
        should_fail: bool,
    }

    impl MockCircuitBreaker {
        fn new(should_fail: bool) -> Self {
            Self { should_fail }
        }
    }

    #[async_trait]
    impl CircuitBreaker for MockCircuitBreaker {
        async fn call(
            &self,
            _service_name: &str,
            func: Box<dyn FnOnce() -> std::pin::Pin<Box<dyn std::future::Future<Output = ServiceResult<Response>> + Send>> + Send>,
        ) -> ServiceResult<Response> {
            if self.should_fail {
                Err(ServiceError::CircuitBreakerOpen("Circuit breaker is open".to_string()))
            } else {
                func().await
            }
        }
        
        async fn call_with_fallback<T, F, Fut, FB>(
            &self,
            _service_name: &str,
            operation: F,
            fallback: FB,
        ) -> ServiceResult<T>
        where
            T: Send + 'static,
            F: FnOnce() -> Fut + Send,
            Fut: std::future::Future<Output = ServiceResult<T>> + Send,
            FB: FnOnce() -> T + Send,
        {
            if self.should_fail {
                Ok(fallback())
            } else {
                operation().await
            }
        }

        async fn state(&self, _service: &str) -> CircuitBreakerState {
            if self.should_fail {
                CircuitBreakerState::Open
            } else {
                CircuitBreakerState::Closed
            }
        }

        async fn metrics(&self, _service: &str) -> CircuitBreakerMetrics {
            CircuitBreakerMetrics {
                total_calls: 0,
                success_calls: 0,
                failed_calls: 0,
                last_failure_time: None,
                state: if self.should_fail { CircuitBreakerState::Open } else { CircuitBreakerState::Closed },
            }
        }
        
        async fn reset(&self, _service_name: &str) -> ServiceResult<()> {
            Ok(())
        }
        
        async fn force_open(&self, _service_name: &str) -> ServiceResult<()> {
            Ok(())
        }
        
        async fn force_close(&self, _service_name: &str) -> ServiceResult<()> {
            Ok(())
        }
    }

    // Router tests
    #[test]
    fn test_route_creation() {
        let route = Route::new("/api/users", "user-service");
        assert_eq!(route.path_prefix, "/api/users");
        assert_eq!(route.service_name, "user-service");
        assert!(route.rewrite_path);
        assert!(route.rules.is_empty());
    }

    #[test]
    fn test_route_with_rewrite() {
        let route = Route::new("/api/users", "user-service").with_rewrite(false);
        assert!(!route.rewrite_path);
    }

    #[test]
    fn test_route_with_rules() {
        let route = Route::new("/api/users", "user-service")
            .add_rule("/old", "/new")
            .add_rule("/v1", "/v2");
        assert_eq!(route.rules.len(), 2);
        assert_eq!(route.rules.get("/old"), Some(&"/new".to_string()));
        assert_eq!(route.rules.get("/v1"), Some(&"/v2".to_string()));
    }

    #[test]
    fn test_router_creation() {
        let router = Router::new();
        // Cannot directly access private fields, so we test behavior instead
        assert!(router.match_route("/unknown/path").is_none());
    }

    #[test]
    fn test_router_add_route() {
        let route = Route::new("/api/users", "user-service");
        let router = Router::new().add_route(route);
        // Test that the route was added by checking if it can be matched
        let result = router.match_route("/api/users/profile");
        assert!(result.is_some());
        let (matched_route, _) = result.unwrap();
        assert_eq!(matched_route.service_name, "user-service");
    }

    #[test]
    fn test_router_match_route_with_rewrite() {
        let route = Route::new("/api/users", "user-service");
        let router = Router::new().add_route(route);

        let (matched_route, remaining_path) = router.match_route("/api/users/profile").unwrap();
        assert_eq!(matched_route.service_name, "user-service");
        assert_eq!(remaining_path, "/profile");
    }

    #[test]
    fn test_router_match_route_without_rewrite() {
        let route = Route::new("/api/orders", "order-service").with_rewrite(false);
        let router = Router::new().add_route(route);

        let (matched_route, remaining_path) = router.match_route("/api/orders/123").unwrap();
        assert_eq!(matched_route.service_name, "order-service");
        assert_eq!(remaining_path, "/api/orders/123");
    }

    #[test]
    fn test_router_no_match() {
        let router = Router::new();
        assert!(router.match_route("/unknown/path").is_none());
    }

    #[test]
    fn test_router_default_route() {
        let default_route = Route::new("/", "default-service");
        let router = Router::new().set_default_route(default_route);

        let (matched_route, remaining_path) = router.match_route("/unknown/path").unwrap();
        assert_eq!(matched_route.service_name, "default-service");
        assert_eq!(remaining_path, "/unknown/path");
    }

    #[test]
    fn test_router_multiple_routes() {
        let route1 = Route::new("/api/users", "user-service");
        let route2 = Route::new("/api/orders", "order-service");
        let route3 = Route::new("/api/products", "product-service");
        
        let router = Router::new()
            .add_route(route1)
            .add_route(route2)
            .add_route(route3);

        // Test each route
        let (matched_route, _) = router.match_route("/api/users/1").unwrap();
        assert_eq!(matched_route.service_name, "user-service");

        let (matched_route, _) = router.match_route("/api/orders/123").unwrap();
        assert_eq!(matched_route.service_name, "order-service");

        let (matched_route, _) = router.match_route("/api/products/abc").unwrap();
        assert_eq!(matched_route.service_name, "product-service");
    }

    // Filter tests
    #[test]
    fn test_auth_filter_creation() {
        let filter = AuthFilter::new(true);
        assert!(filter.required);
        assert!(filter.api_keys.is_empty());
    }

    #[test]
    fn test_auth_filter_add_key() {
        let filter = AuthFilter::new(true)
            .add_key("key1", "service1")
            .add_key("key2", "service2");
        
        assert_eq!(filter.api_keys.len(), 2);
        assert_eq!(filter.api_keys.get("key1"), Some(&"service1".to_string()));
        assert_eq!(filter.api_keys.get("key2"), Some(&"service2".to_string()));
    }

    #[tokio::test]
    async fn test_auth_filter_not_required() {
        let filter = AuthFilter::new(false);
        let headers = HeaderMap::new();
        
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers).await;
        assert!(matches!(result, FilterResult::Continue));
    }

    #[tokio::test]
    async fn test_auth_filter_valid_key() {
        let filter = AuthFilter::new(true).add_key("valid-key", "test-service");
        let mut headers = HeaderMap::new();
        headers.insert("X-API-Key", HeaderValue::from_static("valid-key"));
        
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers).await;
        assert!(matches!(result, FilterResult::Continue));
    }

    #[tokio::test]
    async fn test_auth_filter_invalid_key() {
        let filter = AuthFilter::new(true).add_key("valid-key", "test-service");
        let mut headers = HeaderMap::new();
        headers.insert("X-API-Key", HeaderValue::from_static("invalid-key"));
        
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers).await;
        assert!(matches!(result, FilterResult::Reject(StatusCode::UNAUTHORIZED, _)));
    }

    #[tokio::test]
    async fn test_auth_filter_missing_key() {
        let filter = AuthFilter::new(true);
        let headers = HeaderMap::new();
        
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers).await;
        assert!(matches!(result, FilterResult::Reject(StatusCode::UNAUTHORIZED, _)));
    }

    #[test]
    fn test_rate_limit_filter_creation() {
        let filter = RateLimitFilter::new(10, Duration::from_secs(60));
        assert_eq!(filter.max_requests, 10);
        assert_eq!(filter.window_duration, Duration::from_secs(60));
    }

    #[tokio::test]
    async fn test_rate_limit_filter_client_key_extraction() {
        let filter = RateLimitFilter::new(10, Duration::from_secs(60));
        let mut headers = HeaderMap::new();
        
        // Test with X-Forwarded-For by calling the filter and checking behavior
        headers.insert("X-Forwarded-For", HeaderValue::from_static("192.168.1.1"));
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers.clone()).await;
        assert!(matches!(result, FilterResult::Continue));
        
        // Test with X-Real-IP when X-Forwarded-For is not present
        headers.remove("X-Forwarded-For");
        headers.insert("X-Real-IP", HeaderValue::from_static("10.0.0.1"));
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers.clone()).await;
        assert!(matches!(result, FilterResult::Continue));
        
        // Test with no IP headers
        let empty_headers = HeaderMap::new();
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), empty_headers).await;
        assert!(matches!(result, FilterResult::Continue));
    }

    #[tokio::test]
    async fn test_rate_limit_filter_within_limit() {
        let filter = RateLimitFilter::new(5, Duration::from_secs(60));
        let mut headers = HeaderMap::new();
        headers.insert("X-Forwarded-For", HeaderValue::from_static("192.168.1.1"));
        
        // First request should be allowed
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers.clone()).await;
        assert!(matches!(result, FilterResult::Continue));
        
        // More requests within limit
        for _ in 0..3 {
            let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers.clone()).await;
            assert!(matches!(result, FilterResult::Continue));
        }
    }

    #[tokio::test]
    async fn test_rate_limit_filter_exceed_limit() {
        let filter = RateLimitFilter::new(2, Duration::from_secs(60));
        let mut headers = HeaderMap::new();
        headers.insert("X-Forwarded-For", HeaderValue::from_static("192.168.1.1"));
        
        // First two requests should be allowed
        for _ in 0..2 {
            let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers.clone()).await;
            assert!(matches!(result, FilterResult::Continue));
        }
        
        // Third request should be rejected
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers).await;
        assert!(matches!(result, FilterResult::Reject(StatusCode::TOO_MANY_REQUESTS, _)));
    }

    #[tokio::test]
    async fn test_rate_limit_filter_different_clients() {
        let filter = RateLimitFilter::new(2, Duration::from_secs(60));
        
        let mut headers1 = HeaderMap::new();
        headers1.insert("X-Forwarded-For", HeaderValue::from_static("192.168.1.1"));
        
        let mut headers2 = HeaderMap::new();
        headers2.insert("X-Forwarded-For", HeaderValue::from_static("192.168.1.2"));
        
        // Both clients should be able to make requests up to the limit
        for _ in 0..2 {
            let result1 = filter.filter("GET".to_string(), "/api/test".to_string(), headers1.clone()).await;
            assert!(matches!(result1, FilterResult::Continue));
            
            let result2 = filter.filter("GET".to_string(), "/api/test".to_string(), headers2.clone()).await;
            assert!(matches!(result2, FilterResult::Continue));
        }
        
        // Both should be rejected on the third request
        let result1 = filter.filter("GET".to_string(), "/api/test".to_string(), headers1).await;
        assert!(matches!(result1, FilterResult::Reject(StatusCode::TOO_MANY_REQUESTS, _)));
        
        let result2 = filter.filter("GET".to_string(), "/api/test".to_string(), headers2).await;
        assert!(matches!(result2, FilterResult::Reject(StatusCode::TOO_MANY_REQUESTS, _)));
    }

    #[test]
    fn test_logging_filter_creation() {
        let filter = LoggingFilter::new(log::Level::Info);
        assert_eq!(filter.log_level, log::Level::Info);
    }

    #[tokio::test]
    async fn test_logging_filter_execution() {
        let filter = LoggingFilter::new(log::Level::Debug);
        let mut headers = HeaderMap::new();
        headers.insert("X-Request-ID", HeaderValue::from_static("123"));
        
        let result = filter.filter("GET".to_string(), "/api/test".to_string(), headers).await;
        assert!(matches!(result, FilterResult::Continue));
    }

    #[test]
    fn test_filter_chain_creation() {
        let chain = FilterChain::new();
        // Cannot directly access private fields, so we test behavior
        // For now, just verify the chain was created successfully
        assert!(true, "FilterChain created successfully");
    }

    #[test]
    fn test_filter_chain_add_filter() {
        let auth_filter = Box::new(AuthFilter::new(false));
        let rate_limit_filter = Box::new(RateLimitFilter::new(10, Duration::from_secs(60)));
        
        let chain = FilterChain::new()
            .add_filter(auth_filter)
            .add_filter(rate_limit_filter);
        
        // Cannot directly access private fields, so we test behavior
        // For now, just verify the chain was created successfully with filters
        assert!(true, "FilterChain with filters created successfully");
    }

    // Gateway configuration tests
    #[test]
    fn test_gateway_config_default() {
        let config = GatewayConfig::default();
        assert_eq!(config.server_addr, "0.0.0.0:8080");
        assert_eq!(config.transport_retries, 3);
        assert_eq!(config.transport_timeout, Duration::from_secs(5));
        assert!(matches!(config.load_balancer_strategy, LoadBalancerStrategy::RoundRobin));
    }

    #[test]
    fn test_gateway_config_custom() {
        let mut config = GatewayConfig::default();
        config.server_addr = "localhost:9090".to_string();
        config.transport_retries = 5;
        config.transport_timeout = Duration::from_secs(10);
        
        assert_eq!(config.server_addr, "localhost:9090");
        assert_eq!(config.transport_retries, 5);
        assert_eq!(config.transport_timeout, Duration::from_secs(10));
    }

    #[tokio::test]
    async fn test_gateway_state_creation() {
        let registry = Arc::new(MockRegistry::new());
        let load_balancer = Arc::new(MockLoadBalancer);
        let transport = Arc::new(MockTransport::new(200));
        let circuit_breaker = Arc::new(MockCircuitBreaker::new(false));
        let config = GatewayConfig::default();
        
        let state = GatewayState::new(
            registry.clone(),
            load_balancer.clone(),
            transport.clone(),
            circuit_breaker.clone(),
            config.clone()
        );
        
        assert_eq!(state.config.server_addr, config.server_addr);
    }

    #[tokio::test]
    async fn test_simple_gateway_creation() {
        let registry = Arc::new(MockRegistry::new());
        let load_balancer = Arc::new(MockLoadBalancer);
        let transport = Arc::new(MockTransport::new(200));
        let circuit_breaker = Arc::new(MockCircuitBreaker::new(false));
        let config = GatewayConfig::default();
        
        let state = Arc::new(GatewayState::new(
            registry,
            load_balancer,
            transport,
            circuit_breaker,
            config
        ));
        
        let gateway = SimpleGateway::new(state);
        // Just test that creation works - we won't actually run the server
        assert!(true);
    }

    // Integration-like tests using mocks
    #[tokio::test]
    async fn test_gateway_service_discovery() {
        let registry = Arc::new(MockRegistry::new());
        let load_balancer = Arc::new(MockLoadBalancer);
        let transport = Arc::new(MockTransport::new(200));
        let circuit_breaker = Arc::new(MockCircuitBreaker::new(false));
        let config = GatewayConfig::default();
        
        // Add a test service instance
        let instance = ServiceInstance::new("test-service", "localhost", 8080, "http");
        registry.add_instance("test-service", instance).await;
        
        let state = GatewayState::new(
            registry.clone(),
            load_balancer,
            transport,
            circuit_breaker,
            config
        );
        
        // Test service discovery
        let instances = state.registry.discover("test-service").await.unwrap();
        assert_eq!(instances.len(), 1);
        assert_eq!(instances[0].service_id, "test-service");
        assert_eq!(instances[0].host, "localhost");
        assert_eq!(instances[0].port, 8080);
    }

    #[tokio::test]
    async fn test_gateway_circuit_breaker_integration() {
        let registry = Arc::new(MockRegistry::new());
        let load_balancer = Arc::new(MockLoadBalancer);
        let transport = Arc::new(MockTransport::new(200));
        let circuit_breaker = Arc::new(MockCircuitBreaker::new(true)); // Simulate open circuit breaker
        let config = GatewayConfig::default();
        
        let instance = ServiceInstance::new("test-service", "localhost", 8080, "http");
        registry.add_instance("test-service", instance).await;
        
        let state = GatewayState::new(
            registry,
            load_balancer,
            transport,
            circuit_breaker.clone(),
            config
        );
        
        // Test circuit breaker state
        let cb_state = state.circuit_breaker.state("test-service").await;
        assert_eq!(cb_state, CircuitBreakerState::Open);
    }

    #[tokio::test]
    async fn test_gateway_no_instances_available() {
        let registry = Arc::new(MockRegistry::new());
        let load_balancer = Arc::new(MockLoadBalancer);
        let transport = Arc::new(MockTransport::new(200));
        let circuit_breaker = Arc::new(MockCircuitBreaker::new(false));
        let config = GatewayConfig::default();
        
        let state = GatewayState::new(
            registry.clone(),
            load_balancer,
            transport,
            circuit_breaker,
            config
        );
        
        // Test when no service instances are available
        let instances = state.registry.discover("non-existent-service").await.unwrap();
        assert!(instances.is_empty());
    }

    #[tokio::test]
    async fn test_gateway_load_balancer_integration() {
        let registry = Arc::new(MockRegistry::new());
        let load_balancer = Arc::new(MockLoadBalancer);
        let transport = Arc::new(MockTransport::new(200));
        let circuit_breaker = Arc::new(MockCircuitBreaker::new(false));
        let config = GatewayConfig::default();
        
        // Add multiple instances
        let instance1 = ServiceInstance::new("test-service", "localhost", 8080, "http");
        let instance2 = ServiceInstance::new("test-service", "localhost", 8081, "http");
        registry.add_instance("test-service", instance1).await;
        registry.add_instance("test-service", instance2).await;
        
        let state = GatewayState::new(
            registry.clone(),
            load_balancer.clone(),
            transport,
            circuit_breaker,
            config
        );
        
        let instances = state.registry.discover("test-service").await.unwrap();
        assert_eq!(instances.len(), 2);
        
        // Test load balancer selection
        let selected = state.load_balancer.select("test-service", &instances).await.unwrap();
        assert!(selected.is_some());
        assert_eq!(selected.unwrap().port, 8080); // MockLoadBalancer always returns first instance
    }

    #[tokio::test]
    async fn test_gateway_transport_integration() {
        let registry = Arc::new(MockRegistry::new());
        let load_balancer = Arc::new(MockLoadBalancer);
        let transport = Arc::new(MockTransport::new(200).with_body(b"Hello World".to_vec()));
        let circuit_breaker = Arc::new(MockCircuitBreaker::new(false));
        let config = GatewayConfig::default();
        
        let instance = ServiceInstance::new("test-service", "localhost", 8080, "http");
        
        let state = GatewayState::new(
            registry,
            load_balancer,
            transport.clone(),
            circuit_breaker,
            config
        );
        
        // Test transport call
        let request = Request::new("test-service", "GET", "/api/test");
        let response = state.transport.send(request, &instance).await.unwrap();
        
        assert_eq!(response.status, 200);
        assert_eq!(response.body, Some(b"Hello World".to_vec()));
    }
}